﻿#light

namespace Examples

module OptionMonad =

 open FML.OptionM

 let plus a b c = optionM { let! a' = a
                            let! b' = b
                            let c' = c
                            return (a' + b' + c')
                          }

 let r1 = plus (Some 2) (Some 3) 4
 let r2 = plus None (Some 3) 4
 let r3 = plus (Some 2) None 4
 let r4 = plus None None 4

 printf "%A\n" (r1,r2,r3,r4)

 printf "\nallSome\n"

 let rec allSome l =
    match l with
    |[] -> Some "All Some"
    |h::t -> optionM { let! _ =  h
                       return! (allSome t)
                     }

 let r10 = allSome []
 let r11 = allSome [Some 2; Some 3]
 let r12 = allSome [Some 2; None; Some 3]

 printf "%A\n%A\n%A\n" r10 r11 r12

 let FindAndIncr pred l = optionM { let! x = List.tryFind pred l
                                    return (x+1)
                                  }

 printf "\nFindAndIncr\n"

 printf "%A\n" (FindAndIncr (fun x -> x%2 = 0) [])
 printf "%A\n" (FindAndIncr (fun x -> x%2 = 0) [1;7;4;9;4])
 printf "%A\n" (FindAndIncr (fun x -> x%2 = 0) [3;5;9])



 let runSamples =
  let r1 = plus (Some 2) (Some 3) 4
  let r2 = plus None (Some 3) 4
  let r3 = plus (Some 2) None 4
  let r4 = plus None None 4
  printf "%A\n" (r1,r2,r3,r4)
  printf "\nallSome\n"
  
  let r10 = allSome []
  let r11 = allSome [Some 2; Some 3]
  let r12 = allSome [Some 2; None; Some 3]

  printf "%A\n%A\n%A\n" r10 r11 r12
  
  printf "\nFindAndIncr\n"

  printf "%A\n" (FindAndIncr (fun x -> x%2 = 0) [])
  printf "%A\n" (FindAndIncr (fun x -> x%2 = 0) [1;7;4;9;4])
  printf "%A\n" (FindAndIncr (fun x -> x%2 = 0) [3;5;9])


